#ifndef DNET_H_
#define DNET_H_
#include<iostream>
#include"Graph.h"
#include"ArcNodes.h"
using namespace std;

template<typename Type>
class DNet :public Graph {
	template<typename Type>
	friend istream &operator>>(istream &input, DNet<Type> &DN);
	template<typename Type>
	friend ostream &operator<<(ostream &output, DNet<Type> &DN);
public:
	DNet(int vexnum = 0, int arcnum = 0);
	~DNet();

	Status setSerial(ArcNode<Type>*);
	Status setWeight(Type*);

	ArcNode<Type>* getSerial();
	Type* getWeight();

private:
	ArcNode<Type> *m_pSerial;
	Type *m_tWeight;
};


template<typename Type>
istream &operator>>(istream &input, DNet<Type> &DN){
	ArcNode<Type>* ptr;
	int n = DN.getVexnum();
	for (int i = 0; i < n; ++i) {
		ptr = DN.getSerial()[i].getNext();
		ArcNode<Type> *pt;
		while (ptr != nullptr) {
			pt = ptr->getNext();
			delete ptr;
			ptr = pt;
		}
	}
	delete[] DN.getSerial();
	DN.setSerial(nullptr);
	delete[] DN.getWeight();
	DN.setWeight(nullptr);
	
	int vexnum, arcnum;
	cout << "please input the number of vertex and arc: ";
	input >> vexnum >> arcnum;

	DN.setVexnum(vexnum);
	DN.setArcnum(arcnum);
	DN.setGkind(D);

	ptr = new ArcNode<Type>[vexnum];
	if (ptr == nullptr) {
		perror("Failed to allocate memory!");
		exit(EXIT_FAILURE);
	}
	DN.setSerial(ptr);

	Type *p = new Type[vexnum];
	if (p == nullptr) {
		perror("Failed to allocate memory!");
		exit(EXIT_FAILURE);
	}
	DN.setWeight(p);

	for (int i = 0; i < vexnum; ++i) {
		ptr[i].setIndex(i);
		p[i] = 0;
	}


	cout << "Please input arcs,like this: 1 2 5;" << endl;
	cout << "it means that there is an arc from vex 1 to vex 2,and its weight is 5" << endl;
	int num = arcnum;
	int v1, v2;
	Type w;
	ArcNode<Type> *pt;
	while (num--) {
		cin >> v1 >> v2 >> w;
		--v1; --v2;

		pt = &ptr[v1];
		while (pt->getNext() != nullptr) {
			pt = pt->getNext();
		}

		pt->setNext(new ArcNode<Type>);
		if (pt->getNext() == nullptr) {
			perror("Failed to allocate memory!");
			exit(EXIT_FAILURE);
		}
		pt->getNext()->setIndex(v2);
		pt->getNext()->setWeight(w);
	}
	return input;
}

template<typename Type>
ostream &operator<<(ostream &output, DNet<Type> &DN) {
	ArcNode<Type> *pt, *ptr = DN.getSerial();
	int n = DN.getVexnum();
	for (int i = 0; i < n; ++i) {
		output << ptr[i].getIndex() + 1 << "\t";
		pt = ptr[i].getNext();
		while (pt != nullptr) {
			output << pt->getIndex() + 1 << "--" << pt->getWeight() << "  ";
			pt = pt->getNext();
		}
		output << endl;
	}
	return output;
}

template<typename Type>
DNet<Type>::DNet(int vexnum, int arcnum){

	this->setVexnum(vexnum);
	this->setArcnum(arcnum);
	this->setGkind(D);

	ArcNode<Type> *ptr = new ArcNode<Type>[vexnum];
	if (ptr == nullptr) {
		perror("Failed to allocate memory!");
		exit(EXIT_FAILURE);
	}
	this->setSerial(ptr);

	Type *p = new Type[vexnum];
	if (p == nullptr) {
		perror("Failed to allocate memory!");
		exit(EXIT_FAILURE);
	}
	this->setWeight(p);

	for (int i = 0; i < vexnum; ++i) {
		ptr[i].setIndex(i);
		p[i] = 0;
	}

	
	cout << "Please input arcs,like this: 1 2 5;" << endl;
	cout << "it means that there is an arc from vex 1 to vex 2,and its weight is 5" << endl;
	int num = arcnum;
	int v1, v2;
	Type w;
	ArcNode<Type> *pt;
	while (num--) {
		cin >> v1 >> v2 >> w;
		--v1; --v2;

		pt = &ptr[v1];
		while (pt->getNext() != nullptr) {
			pt = pt->getNext();
		}

		pt->setNext(new ArcNode<Type>);
		if (pt->getNext() == nullptr) {
			perror("Failed to allocate memory!");
			exit(EXIT_FAILURE);
		}
		pt->getNext()->setIndex(v2);
		pt->getNext()->setWeight(w);
	}
}

template<typename Type>
DNet<Type>::~DNet(){
	ArcNode<Type>* ptr;
	int n = this->getVexnum();
	for (int i = 0; i < n; ++i) {
		ptr = this->getSerial()[i].getNext();
		ArcNode<Type> *pt;
		while (ptr != nullptr) {
			pt = ptr->getNext();
			delete ptr;
			ptr = pt;
		}
	}
	delete[] this->getSerial();
	this->setSerial(nullptr);
	delete[] this->getWeight();
	this->setWeight(nullptr);
}

template<typename Type>
inline Status DNet<Type>::setSerial(ArcNode<Type> *serial){
	m_pSerial = serial;
	return OK;
}

template<typename Type>
inline Status DNet<Type>::setWeight(Type *weight){
	m_tWeight = weight;
	return OK;
}

template<typename Type>
inline ArcNode<Type> * DNet<Type>::getSerial(){
	return m_pSerial;
}

template<typename Type>
inline Type * DNet<Type>::getWeight(){
	return m_tWeight;
}

#endif